from django.db import transaction
from rest_framework import generics
from rest_framework import serializers
from apps.goods.models import GoodsVisitCount, SPUSpecification, SPU, SpecificationOption, SKU, GoodsCategory, \
    SKUSpecification
from apps.users.models import User
from celery_tasks.detail.tasks import get_detail_html


# SKU规格表序列化器
class SKUSpecificationSerialzier(serializers.Serializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()
    # class Meta:
    #     model = SKUSpecification
    #     # 返回列表时可以直接获取外建_id
    #     fields = ("spec_id", 'option_id')


# 获取sku表数据
class SkUSerializer(serializers.ModelSerializer):
    # 获取商品的规格选项
    # specs = SKUSpecificationSerialzier(read_only=True, many=True)
    # 新增时  specs设置为只读会接受不到数据   1:n时  1端的数据可以不写read-only不会报错
    specs = SKUSpecificationSerialzier(many=True)
    # 关联嵌套返回spu表的商品名
    spu = serializers.StringRelatedField(read_only=True)
    category = serializers.StringRelatedField(read_only=True)
    # specs = SK回关联category的id值USpecificationSerialzier(read_only=True, many=True)
    # 返
    category_id = serializers.IntegerField()
    # 返回关联spu的id值
    spu_id = serializers.IntegerField()

    class Meta:
        model = SKU
        fields = "__all__"
    def create(self, validated_data):
        print(validated_data)
        specs = validated_data.pop("specs")
        # 禁止自动提交
        with transaction.atomic():
            # 开启事务
            sid = transaction.savepoint()
            try:
                # super()在子类中可以调用父类的方法或属性  得到sku对象
                sku = super().create(validated_data)
                for spec in specs:
                    # sku规格对象要指定sku_id,spec_id,option_id
                    spec["sku_id"] = sku.id
                    SKUSpecification.objects.create(**spec)
            except:
                # 捕获异常，说明数据库操作失败，进行回滚
                transaction.savepoint_rollback(sid)
                raise serializers.ValidationError('数据库错误')
            else:
                # 没有捕获异常，数据库操作成功，进行提交
                transaction.savepoint_commit(sid)
                # 执行异步任务生成新的静态页面
                sku_id = sku.id
                get_detail_html.delay(sku_id)
                return sku
        # # self指的是当前序列化器对象，在self下面有个context属性保存了请求对象
        # specs = self.context['request'].data.get('specs')
        # # 禁止自动提交
        # with transaction.atomic():
        #     # 开启事务
        #     sid = transaction.savepoint()
        #     try:
        #         # 1、保存sku表
        #         sku = SKU.objects.create(**validated_data)
        #         # 2、保存SKU具体规格
        #         for spec in specs:
        #             SKUSpecification.objects.create(sku_id=sku.id, spec_id=spec['spec_id'], option_id=spec['option_id'])
        #     except:
        #         # 捕获异常，说明数据库操作失败，进行回滚
        #         transaction.savepoint_rollback(sid)
        #         raise serializers.ValidationError('数据库错误')
        #     else:
        #         # 没有捕获异常，数据库操作成功，进行提交
        #         transaction.savepoint_commit(sid)
        #         # 执行异步任务生成新的静态页面
        #         get_detail_html.delay(sku.id)
        #         return sku
        # ================================================

    def update(self, instance, validated_data):
        specs = self.context["request"].data.get("specs")
        # with transaction.atomic():
        #     # 开启事务
        #     sid = transaction.savepoint()
        #     try:
        #     # 1、更新sku表
        #         SKU.objects.filter(id=instance.id).update(**validated_data)
        #         for spec in specs:
        #             SKUSpecification.objects.create(sku=instance, spec_id=spec['spec_id'], option_id=spec['option_id'])
        #     except:
        #         # 捕获异常，说明数据库操作失败，进行回滚
        #         transaction.savepoint_rollback(sid)
        #         raise serializers.ValidationError('数据库错误')
        #     else:
        #         # 没有捕获异常，数据库操作成功，进行提交
        #         transaction.savepoint_commit(sid)
        #         # 执行异步任务生成新的静态页面
        #         get_detail_html.delay(instance.id)
        #         return instance
        specs = validated_data.pop("specs")
        with transaction.atomic():
            # 开启事务
            sid = transaction.savepoint()
            try:
                # 使用父类方法
                instance = super().update(instance,validated_data)
                # 删除规格
                SKUSpecification.objects.filter(sku_id=instance.id).delete()

                for spec in specs:
                    spec["sku_id"] = instance.id
                    SKUSpecification.objects.create(**spec)
            except:
                # 捕获异常，说明数据库操作失败，进行回滚
                transaction.savepoint_rollback(sid)
                raise serializers.ValidationError('数据库错误')
            else:
                # 没有捕获异常，数据库操作成功，进行提交
                transaction.savepoint_commit(sid)
                # 执行异步任务生成新的静态页面
                get_detail_html.delay(instance.id)
                return instance


# 获取sku的三级分类
class SKUCategorieSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = "__all__"


# 获取sku的spu信息
class SPUOptineSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = ["id","value"]

# 获取spu规格数据
class SPUSpecSerialzier(serializers.ModelSerializer):
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField(read_only=True)
    options = SPUOptineSerializer(read_only=True,many=True)
    class Meta:
        model = SPUSpecification
        fields = "__all__"


